/*
 * ASTCpp.cpp
 *
 *  Created on: Sep 10, 2012
 *      Author: Hernan
 */

#include "ArbolSintactico.h"
#include "../logger/logger.h"


ArbolSintactico::ArbolSintactico(Nodo* raiz){
	this->raiz=raiz;
}

ArbolSintactico::ArbolSintactico(){
	this->raiz=NULL;
	this->pathYAML="";
	this->nodoActual=NULL;
}


ArbolSintactico::ArbolSintactico(string fichero) {

	this->pathYAML= fichero;

	this->raiz = NULL;

	this->nodoActual = raiz;

}


void ArbolSintactico::setNodoActual(Nodo* actual){

	this->nodoActual=actual;
}

Nodo* ArbolSintactico::getRaiz(){

	return this->raiz;

}





Nodo* ArbolSintactico::buscarNodo(string str){
	Nodo* actual= this->nodoActual;
	Nodo* encontrado=NULL;
	this->buscarRecursivo(actual, encontrado, str);
	return encontrado;
}


void ArbolSintactico::buscarRecursivo(Nodo* nodo,Nodo* &encontrado, string buscado){

	if (nodo!=NULL){

		if (strcmp(nodo->getTipoDato().c_str(),buscado.c_str())==0){encontrado=nodo;}

		else if (!nodo->obtenerLista()->empty()){
			list<Nodo*>::iterator it= nodo->obtenerLista()->begin();
			while(it!=nodo->obtenerLista()->end() && encontrado==NULL){
				buscarRecursivo(*it, encontrado, buscado);
				it++;
			}
		}
	}
}



void ArbolSintactico::cargarArbol(){

		ifstream archivo(this->pathYAML.c_str());

		if (archivo.is_open()){

			stack<Nodo*> pila;

			cargarArbolRecursivo(pila, archivo);

		    archivo.close();
		} else {
			Logger logger("log.txt");
			logger.escribirLinea("No existe el archivo YAML pasado como argumento.",__FILE__,__LINE__);
			logger.cerrar();
		}

		this->normalizar();

		this->nodoActual=this->raiz;

}



void ArbolSintactico::cargarArbolRecursivo(stack<Nodo*> pilaNodos, ifstream& archivo){

	if (!archivo.eof()){

		char* buffer=new char[500];

		archivo.getline(buffer,500,'\n');

		string str(buffer);

		Nodo* nuevoNodo=new Nodo(str); //hay q normalizar despues. y agregar el caso de que haya mas de una raiz

		if (pilaNodos.empty()){

			this->raiz=nuevoNodo;

			pilaNodos.push(nuevoNodo);

			cargarArbolRecursivo(pilaNodos,archivo);

			return;
		}

		while( (this->existeShift(pilaNodos, nuevoNodo)==0) || (this->existeShift(pilaNodos, nuevoNodo)<0)){

			//cout<<"              popeo"<<endl;
			//cout<<"-------------------"<<endl;
			pilaNodos.pop();


		}

		if (this->existeShift(pilaNodos, nuevoNodo)>0) {
			//cout<<"              mando como hijo"<<endl;
			//cout<<"-----------------------------"<<endl;
			pilaNodos.top()->agregarPtr(nuevoNodo);
			pilaNodos.push(nuevoNodo);
			cargarArbolRecursivo(pilaNodos,archivo);
		}

	}

}


void ArbolSintactico::normalizar(){

	Nodo* nodo=raiz;

	stack<Nodo*> pila;

	this->normalizarRecursivo(nodo,pila);

}




void ArbolSintactico::normalizarRecursivo(Nodo* nodo, stack<Nodo*> pila){

	if (nodo==NULL){
		return;
	}

	else{
		nodo->normalizar();
		if (!nodo->obtenerLista()->empty()){
			pila.push(nodo);
			list<Nodo*>::iterator it= nodo->obtenerLista()->begin();
			while(it!=nodo->obtenerLista()->end()){
				normalizarRecursivo(*it,pila);
				it++;
			}
			pila.pop();
		}
		else {

			pila.pop();
		}
	}
}




int ArbolSintactico::existeShift(stack<Nodo*> pilaNodos, Nodo* nuevoNodo){

	string cadena2= nuevoNodo->getDato();

	string cadena1= pilaNodos.top()->getDato();
	//cout<<"c2:"<<cadena2<<endl;
	//cout<<"c1:"<<cadena1<<endl;

	int i1=0;
	int i2=i1;

	while ((cadena1[i1]==' ')){
		i1++;
	}
	while ((cadena2[i2]==' ')){
		i2++;
	}

	return (i2-i1);
}



void ArbolSintactico::imprimir(){
	this->raiz->imprimir();
}



ArbolSintactico::~ArbolSintactico() {
	delete this->nodoActual;
	delete this->raiz;
}


